package com.seaengine.net
{
	import com.seaengine.util.NetUtils;
	
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	/**
	 *处理51Game 协议，包头，加解密 
	 * 
	 * 
	 */
	public class GYnetProtocol extends Int32QueueProtocol
	{
		
		public const TIME_OFF:int = 500;
		
		protected var _playID:int			= -1;
		 
		public var timestamp:Number;
		private var oneTurnEnd:Boolean=true;
		private var msgCache:Array=new Array();
		private var m_timer:Timer;
		public function GYnetProtocol(host:String=null, port:int=0)
		{
			super(host, port);
			m_timer=new Timer(200, 0);
			m_timer.start();
			m_timer.addEventListener(TimerEvent.TIMER,onTimeFrame)	
			this.addEventListener(ProtocolEvent.DECODE_PACKAGE,onDecodePackage);
		}
		
		
		/**
		 * implement in child class  
		 * @param messageID
		 * @param body
		 * 
		 */
		protected function dispatchResponse(messageID:int,body:JoyPortBuffer):void
		{
			oneTurnEnd=true;
			//Common.debug(body);
		}
		
		override protected function onReceivedIntegrityData(data:JoyPortBuffer) : void
		{
			//super.onReceivedIntegrityData(data);
			decodePackage(data);
		}
		
		private function decodePackage(data:JoyPortBuffer):void
		{
			var header:Object 		= new Object();
			
			header.serialNumber = data.decodeInt16();
			header.messageID = data.decodeInt16();
			header.CRC = data.decodeUInt32();
			header.bodyLength = data.decodeInt16();			
			header.MagicNumber = data.decodeInt16();
			
			if(!header.bodyLength || header.MagicNumber != 0x3B8E )
				return;
			
			var body:JoyPortBuffer = data.truncateBuffer(data.position,header.bodyLength);
			
			if(NetUtils.computeCRC32(body,body.length) != header.CRC)
				return;
			
			header.body	= body;
			var event:ProtocolEvent = new ProtocolEvent(ProtocolEvent.DECODE_PACKAGE);
			event.result = header;
			dispatchEvent(event);
			
		}
		
		protected function onDecodePackage(e:ProtocolEvent):void
		{
			var body:JoyPortBuffer	  = JoyPortBuffer(e.result.body);
			var messageID:int = int(e.result.messageID);			
			dispatchResponse(messageID,body);
		}
		
		private function onTimeFrame(evt:TimerEvent):void
		{			
			if(msgCache.length>0 && oneTurnEnd)
			{
				var temp:Object=msgCache.shift();
				var _messageID:int=temp["_messageID"];
				var _body:JoyPortBuffer=temp["_body"];
				sendMessageImmediately(_messageID,_body)
			}
		}
		
		/**
		 * 
		 * @param messageID
		 * @param body
		 * @param signature
		 * 
		 */
		protected function sendMessage(_messageID:int,_body:JoyPortBuffer):void
		{
			var tempObj:Object=new Object();
			tempObj["_messageID"] = _messageID;
			tempObj["_body"] = _body;
			msgCache.push(tempObj);
		}
		protected function sendMessageImmediately(_messageID:int,_body:JoyPortBuffer):void
		{
			oneTurnEnd=false;
			var newDate:Date = new Date();
			timestamp = newDate.time;
			
			
			_currentMessage 		= _messageID;
			var bodyLength:uint		= _body.length;
			var sendBuffer:JoyPortBuffer 	= new JoyPortBuffer();
				
			//serialNumber
			sendBuffer.encodeInt16(m_serialNumber);  
			m_serialNumber++;
			//messageID
			sendBuffer.encodeInt16(_messageID);
			//CRC
			sendBuffer.encodeInt32(NetUtils.computeCRC32(_body,_body.length));
			//载荷部分字节数
			sendBuffer.encodeInt16(bodyLength);
			//魔术验证字，恒等于0x3B8E
			sendBuffer.encodeInt16(0x3B8E);
						
			sendBuffer.append(_body);  //body
			
			super.send(sendBuffer);
			if ( !connected )
				this.connect(host,port);
		}
				
		protected function decodeString(data:JoyPortBuffer):String
		{
			var len:int = data.decodeInt16();
			if ( len > data.bytesAvailable )
				return "";
			var s:String = data.readMultiByte(len,"utf-8");
			return s;
		}
		
		protected function encodeString(data:JoyPortBuffer,s:String):void
		{
			var buffer:JoyPortBuffer = new JoyPortBuffer();
			if(!s)
				data.encodeInt16(0);
			buffer.encodeString(s+String.fromCharCode(0));
			data.encodeInt16(buffer.length);
			data.encodeBytes(buffer);
		}
		
		protected function decodeRawBuffer(data:JoyPortBuffer):JoyPortBuffer
		{
			var len:int = data.decodeInt16();
			return data.truncateBuffer(data.position,len);
		}
		
		protected function succeed(data:JoyPortBuffer):Boolean 
		{
			return (data.decodeInt16() == 0);
		}
		
	}
}